﻿using System.Net.Http;
using System.ServiceModel.Channels;
using System.Web;
using AutoMapper;
using Enferno.Public.InversionOfControl;
using Enferno.Public.Web.Builders;
using Enferno.Public.Web.Components.Server.Helpers;
using Enferno.Public.Web.Components.Server.ViewModels;
using Enferno.Public.Web.Models;
using Enferno.Public.Web.Repositories;
using Enferno.StormApiClient.Shopping;
using Enferno.Web.StormUtils;
using Microsoft.Practices.Unity;

namespace Enferno.Public.Web.Components.Server.Managers
{
    public class BasketManager
    {
        private readonly IRepository _repository; 
        private readonly BasketBuilder _basketBuilder;
        private readonly BasketViewModel _emptyBasket = new BasketViewModel {Id = "0"};

        public BasketManager()
        {
            _repository = IoC.Container.Resolve<IRepository>();
            _basketBuilder = new BasketBuilder();
        }

        public BasketViewModel GetBasket(HttpRequestMessage request)
        {
            if (StormContext.BasketId.HasValue)
            {
                var basket = _repository.Shopping.GetBasket(StormContext.BasketId.Value);

                if (!IsValidBasket(basket))
                    return _emptyBasket;

                var basketModel = _basketBuilder.MapBasketModel(basket);

                return Mapper.Map<BasketViewModel>(basketModel);
            }
            return _emptyBasket;
        }

        public BasketViewModel AddItem(int basketId, BasketItemViewModel basketItemViewModel)
        {
            Basket basket = null;

            if (basketId > 0)
                basket = _repository.Shopping.GetBasket(basketId);

            if (!IsValidBasket(basket))
                basket = _repository.Shopping.CreateBasket(RequestHelpers.GetClientIp(null));

            var basketItemModel = Mapper.Map<BasketItemModel>(basketItemViewModel);
            var basketItem = _basketBuilder.MapBasketItem(basketItemModel);
            var updatedBasket = _repository.Shopping.AddItemToBasket(basket.Id.GetValueOrDefault(), basketItem);
            var updatedBasketModel = _basketBuilder.MapBasketModel(updatedBasket);
            return Mapper.Map<BasketViewModel>(updatedBasketModel);
        }

        private static bool IsValidBasket(Basket basket)
        {
            return basket != null && basket.IsEditable;
        }

        public BasketViewModel UpdateItem(int basketId, BasketItemViewModel basketItemViewModel)
        {
            Basket basket = null;

            if(basketId > 0 )
                basket = _repository.Shopping.GetBasket(basketId);

            if (!IsValidBasket(basket))
            {
                StormContext.BasketId = null;
                return _emptyBasket;
            }

            var basketItemModel = Mapper.Map<BasketItemModel>(basketItemViewModel);
            var basketItem = _basketBuilder.MapBasketItem(basketItemModel);
            var updatedBasket = _repository.Shopping.UpdateBasketItem(basketId, basketItem);
            var updatedBasketModel = _basketBuilder.MapBasketModel(updatedBasket);
            return Mapper.Map<BasketViewModel>(updatedBasketModel);
        }

        public BasketViewModel DeleteItem(int basketId, int itemLineNo)
        {
            Basket basket = null;

            if (basketId > 0)
                basket = _repository.Shopping.GetBasket(basketId);

            if (!IsValidBasket(basket))
            {
                StormContext.BasketId = null;
                return _emptyBasket;
            }

            var updatedBasket = _repository.Shopping.DeleteBasketItem(basketId, itemLineNo);
            var updatedBasketModel = _basketBuilder.MapBasketModel(updatedBasket);
            return Mapper.Map<BasketViewModel>(updatedBasketModel);
        }

        public BasketViewModel ApplyDiscount(int basketId, string promotionCode)
        {
            if (basketId == 0)
                return _emptyBasket;

            var updatedBasket = _repository.Shopping.ApplyDiscount(basketId, promotionCode);
            var updatedBasketModel = Mapper.Map<Basket, BasketModel>(updatedBasket);
            return Mapper.Map<BasketModel, BasketViewModel>(updatedBasketModel);
        }

        public BasketViewModel RemovePromotion(int basketId, int promotionId, bool resetDiscount = false)
        {
            var updatedBasket = _repository.Shopping.RemovePromotion(basketId, promotionId, resetDiscount);
            var updatedBasketModel = Mapper.Map<Basket, BasketModel>(updatedBasket);
            return Mapper.Map<BasketModel, BasketViewModel>(updatedBasketModel);
        }
    }
}
